//
//  PlayDetailViewController.swift
//  TimMusic
//
//  Created by nkl on 2024/10/11.
//

import Combine
import Foundation
import Kingfisher
import TSVideoKit
import UIKit
import WidgetKit

class PlayDetailViewController: BasicViewController {
    lazy var backButton: UIButton = {
        let btn = UIButton()
        btn.setImage(UIImage(named: "ic_dismiss"), for: .normal)
        btn.addTarget(self, action: #selector(dismissCurrentVc), for: .touchUpInside)
        return btn
    }()

    lazy var skinButton: UIButton = {
        let btn = UIButton()
        btn.setImage(UIImage(named: "ic_skin"), for: .normal)
        btn.addTarget(self, action: #selector(showSkinViewController), for: .touchUpInside)
        btn.isHidden = true
        return btn
    }()

    lazy var playerView: UIView = .simpleView(color: .yellow)
    lazy var titleLabel: UILabel = .simpleLabel(text: "--", font: .boldSystemFont36, color: .white)
    lazy var detailLabel: UILabel = .simpleLabel(text: "--", font: .boldSystemFont18, color: .white)
    lazy var favorite: UIButton = {
        let btn = UIButton()
        btn.setImage(UIImage(named: "ic_fav_white"), for: .normal)
        btn.setImage(UIImage(named: "ic_fav_light"), for: .selected)
        btn.isSelected = TSVideoOperator.shared.playerViewModel.currentVideo?.isFavorite ?? false
        return btn
    }()

    lazy var controlView: PlayDetailControlView = PlayDetailControlView()
    lazy var progressView: PlayDetailProgressView = {
        let progress = PlayDetailProgressView()
        progress.progressBar.delegate = self
        return progress
    }()

    lazy var musicPlaceHolderView: UIImageView = .simpleImage(imageName: "ic_placeholder")

    var playerVc: TSVideoPlayController {
        TSVideoOperator.shared.playerController
    }

    private var cancellable: [AnyCancellable] = []

    // MARK: - 点击方法

    @objc func nextMode() {
        PlayDetailManager.shared.nextMode()
    }

    @objc func dismissCurrentVc() {
        PlayDetailManager.shared.hiddePlayDetailVc()
    }

    @objc func playOrPause() {
        PlayDetailManager.shared.pauseOrPlay()
    }

    @objc func playNext() {
        PlayDetailManager.shared.playNext()
    }

    @objc func playLast() {
        PlayDetailManager.shared.playLast()
    }

    @objc func likeButtonAction() {
        if let currentVc = TSVideoOperator.shared.playerViewModel.currentVideo {
            if currentVc.isFavorite {
                TSVideoOperator.shared.dataManager.dislikeCurrentVideo { [weak self] vd in
                    guard let self = self else {
                        return
                    }
                    self.favorite.isSelected = vd.isFavorite
                }
            } else {
                TSVideoOperator.shared.dataManager.likeCurrentVideo { [weak self] vd in
                    guard let self = self else {
                        return
                    }
                    self.favorite.isSelected = vd.isFavorite
                }
            }
        }
    }

    @objc func showSkinViewController() {
        let vc = PlayDetailSkinViewController()
        vc.modalPresentationStyle = .overFullScreen
        present(vc, animated: true)
    }

    @objc func showPlaylistController() {
        let vc = PlayDetailRecommendListVc()
        vc.modalPresentationStyle = .overFullScreen
        present(vc, animated: true)
    }

    override func viewDidLoad() {
        super.viewDidLoad()
        addPlayNotifaction()
        view.backgroundColor = .black
    }

    override func addChildren() {
        super.addChildren()
        view.addSubview(backButton)
        view.addSubview(skinButton)
        view.addSubview(playerVc.view)
        view.addSubview(titleLabel)
        view.addSubview(detailLabel)
        view.addSubview(favorite)
        view.addSubview(controlView)
        view.addSubview(progressView)
        view.addSubview(musicPlaceHolderView)
        addTargets()
    }

    func addPlayNotifaction() {
//        playerVc.viewModel.$loadState.receive(on: DispatchQueue.main).sink { [weak self] state in
//            guard let self = self else { return }
//            self.loadingStateChangeHandler(state: state)
//        }.store(in: &cancellable)

        playerVc.viewModel.$currentTime.receive(on: DispatchQueue.main).sink { [weak self] timeValue in
            guard let self = self else { return }
            self.progressView.updateTime(currentTime: timeValue, duration: self.playerVc.player.duration)
            TMTabbarViewController.rootTabbar?.customBar.updateTime(time: timeValue.mmsshh)
            TMTabbarViewController.rootTabbar?.customBar.startRotationAnimation()

        }.store(in: &cancellable)

        playerVc.viewModel.$playStatus.receive(on: DispatchQueue.main).sink { [weak self] status in
            guard let self = self else { return }
            self.playStatusChangeHandler(status)

        }.store(in: &cancellable)

        playerVc.viewModel.$loopMode.receive(on: DispatchQueue.main).sink { [weak self] loop in
            guard let self = self else { return }
            self.controlView.modelBtn.setImage(UIImage(named: loop.icon), for: .normal)
        }.store(in: &cancellable)

        playerVc.viewModel.$currentVideo.receive(on: DispatchQueue.main).dropFirst().scan((nil, nil)) { previous, current in
            (previous.1, current)
        }.sink { [weak self] oldValue, newValue in
            guard let self = self else { return }
            /// 即将播放的和正在播放的视频是同一个
            if newValue != nil &&
                oldValue?.videoId == newValue?.videoId {
                PlayDetailManager.shared.showPlayDetailVc()
                return
            }

            if let mVideo = newValue {
                self.updateVideoInfo(video: mVideo)
                self.updateWidgetStatus(video: mVideo)
                TMTabbarViewController.rootTabbar?.customBar.updateVideoImage(video: mVideo)
            }

            NotificationCenter.default.post(name: kDataChangedNotifactionName, object: nil)
        }.store(in: &cancellable)

        let pan = UIPanGestureRecognizer(target: self, action: #selector(handlePanGesture(gesture:)))
        view.addGestureRecognizer(pan)
    }

    @objc func handlePanGesture(gesture: UIPanGestureRecognizer) {
        let translate = gesture.translation(in: view)
        if gesture.state == .ended {
            if translate.y > 50 {
                PlayDetailManager.shared.hiddePlayDetailVc()
            }
        }
    }

    func updateWidgetPlayStatus(isPlaying: Bool) {
        let sharedDefaults = UserDefaults(suiteName: TimeGroupName)
        sharedDefaults?.set(isPlaying, forKey: "widgetPlay")
        WidgetCenter.shared.reloadAllTimelines()
    }

    func updateWidgetStatus(video: TSVideo) {
        let sharedDefaults = UserDefaults(suiteName: TimeGroupName)
        sharedDefaults?.set(video.title ?? "Unknown", forKey: "widgetTitle")
        sharedDefaults?.set(video.artist ?? "Unknown", forKey: "widgetDetail")
        if let data = video.artwork {
            let finalImgData = UIImage(data: data)?.compressImageToSize()
            sharedDefaults?.set(finalImgData, forKey: "widgetImageData")
            WidgetCenter.shared.reloadAllTimelines()
        } else {
            if let dataUrl = video.iconUrl {
                let downloader = ImageDownloader.default

                downloader.downloadImage(with: dataUrl) { result in

                    let nDefaults = UserDefaults(suiteName: TimeGroupName)
                    switch result {
                    case let .success(value):
                        let imageData = value.originalData
                        let finalImgData = UIImage(data: imageData)?.compressImageToSize()
                        nDefaults?.set(finalImgData, forKey: "widgetImageData")
                    case .failure:
                        if let imgData = UIImage(named: "ic_placeholder")?.compressImageToSize() {
                            nDefaults?.set(imgData, forKey: "widgetImageData")
                        } else {
                            nDefaults?.set(nil, forKey: "widgetImageData")
                        }
                    }
                    WidgetCenter.shared.reloadAllTimelines()
                }
            } else {
                if let imgData = UIImage(named: "ic_placeholder")?.compressImageToSize() {
                    sharedDefaults?.set(imgData, forKey: "widgetImageData")
                } else {
                    sharedDefaults?.set(nil, forKey: "widgetImageData")
                }
                WidgetCenter.shared.reloadAllTimelines()
            }
        }
    }

    func addTargets() {
        favorite.addTarget(self, action: #selector(likeButtonAction), for: .touchUpInside)
        controlView.modelBtn.addTarget(self, action: #selector(nextMode), for: .touchUpInside)
        controlView.playlistBtn.addTarget(self, action: #selector(showPlaylistController), for: .touchUpInside)
        controlView.playBtn.addTarget(self, action: #selector(playOrPause), for: .touchUpInside)
        controlView.lastBtn.addTarget(self, action: #selector(playLast), for: .touchUpInside)
        controlView.nextBtn.addTarget(self, action: #selector(playNext), for: .touchUpInside)
    }

    fileprivate func updateVideoInfo(video: TSVideo) {
        titleLabel.text = video.title
        detailLabel.text = video.artist
        favorite.isSelected = video.isFavorite

        if video.isAudio {
            if let data = TSVideoOperator.shared.playerViewModel.currentVideo?.artwork, let img = UIImage(data: data) {
                musicPlaceHolderView.image = img
            } else {
                musicPlaceHolderView.kf.setImage(with: video.iconUrl, placeholder: UIImage(named: "ic_placeholder"))
            }

            musicPlaceHolderView.isHidden = false
        } else {
            musicPlaceHolderView.isHidden = true
            musicPlaceHolderView.image = UIImage(named: "ic_placeholder")
        }
    }

    fileprivate func playStatusChangeHandler(_ status: VLCMediaPlayerState) {
        if status == .playing {
            controlView.playBtn.playingState = .playing
            TMTabbarViewController.rootTabbar?.customBar.updateState(isPlaying: true)
//            updatePlaceHoderView(video: playControl.viewModel.currentVideo, status: status)
//            if let video = playControl.viewModel.currentVideo {
//                PlayerManager.shared.miniBar.updateVideoInfo(video: video, state: .playing)
//            }
            updateWidgetPlayStatus(isPlaying: true)
            TMTabbarViewController.rootTabbar?.customBar.startRotationAnimation()

        } else if status == .paused || status == .ended || status == .stopped {
            controlView.playBtn.playingState = .pause
            TMTabbarViewController.rootTabbar?.customBar.updateState(isPlaying: false)
            updateWidgetPlayStatus(isPlaying: false)
            TMTabbarViewController.rootTabbar?.customBar.stopRotating()

//            if let video = playControl.viewModel.currentVideo {
//                PlayerManager.shared.miniBar.updateVideoInfo(video: video, state: .pause)
//            }
        } else if status == .buffering {
            /// 缓冲了展示loading
//            if !playControl.player.isPlaying && !controlView.progressView.isDragging {
//                showLoading()
//            } else {
//                hideLoading()
//            }
        }
    }

    override func makeConstraints() {
        super.makeConstraints()
        backButton.snp.makeConstraints { make in
            make.top.equalTo(view.safeAreaLayoutGuide.snp.top)
            make.width.height.equalTo(24)
            make.leading.equalToSuperview().offset(16)
        }

        skinButton.snp.makeConstraints { make in
            make.trailing.equalToSuperview().offset(-16)
            make.centerY.equalTo(backButton)
            make.width.height.equalTo(24)
        }

        playerVc.view.snp.makeConstraints { make in
            make.leading.trailing.equalToSuperview()
            make.height.equalTo(400 * (UIScreen.kScreenHeight / 896.0))
            make.top.equalTo(backButton.snp.bottom).offset(50 * (UIScreen.kScreenHeight / 896.0))
        }

        musicPlaceHolderView.snp.makeConstraints { make in
            make.center.equalTo(playerVc.view)
            make.width.height.equalTo(300)
        }

        titleLabel.snp.makeConstraints { make in
            make.leading.trailing.equalToSuperview()
            make.top.equalTo(playerVc.view.snp.bottom).offset(50 * (UIScreen.kScreenHeight / 896.0))
        }

        detailLabel.snp.makeConstraints { make in
            make.leading.equalToSuperview()
            make.top.equalTo(titleLabel.snp.bottom).offset(12)
            make.trailing.equalTo(favorite.snp.leading).offset(-16)
        }

        favorite.snp.makeConstraints { make in
            make.trailing.equalToSuperview().offset(-16)
            make.width.height.equalTo(24)
            make.centerY.equalTo(detailLabel)
        }

        controlView.snp.makeConstraints { make in
            make.top.equalTo(detailLabel.snp.bottom).offset(24)
            make.leading.trailing.equalToSuperview()
        }

        progressView.snp.makeConstraints { make in
            make.leading.trailing.equalToSuperview().inset(8)
            make.bottom.equalTo(view.safeAreaLayoutGuide.snp.bottom)
        }
    }
}

extension PlayDetailViewController: SJProgressSliderDelegate {
    func sliderWillBeginDragging(_ slider: SJProgressSlider) {
        playerVc.pause()
    }

    func slider(_ slider: SJProgressSlider, valueDidChange value: CGFloat) {
        if slider.isDragging {
            playerVc.seekToProgress(progress: slider.value) { _ in }
        }
        let durationTime = playerVc.player.duration
        let currentTime = durationTime * value
        progressView.updateTime(currentTime: currentTime, duration: durationTime)
    }

    func sliderDidEndDragging(_ slider: SJProgressSlider) {
        playerVc.play()
    }
}
